package com.shigu.mo.services;

import com.opentae.data.mall.beans.*;
import com.opentae.data.mall.examples.*;
import com.opentae.data.mall.interfaces.*;
import com.shigu.agent.bo.AgentBO;
import com.shigu.agent.enums.UserRoleType;
import com.shigu.agent.exceptions.AgentException;
import com.shigu.agent.exceptions.YeepayException;
import com.shigu.agent.processes.AgentProcess;
import com.shigu.main4.common.util.BeanMapper;
import com.shigu.main4.common.util.MoneyUtil;
import com.shigu.main4.common.util.SecretUtil;
import com.shigu.mo.exceptions.MoException;

import com.shigu.mo.vo.*;
import com.shigu.mo.vo.responses.AgentSelBusrateResponse;
import com.shigu.mo.vo.responses.RateDetailResponse;
import com.shigu.passageway.Passageway;
import com.shigu.passageway.bo.RegistBO;
import com.shigu.passageway.exceptions.PassagewayException;
import com.shigu.route.PassagewayRoute;
import com.yeepay.skb.biz.FeeSetPartsBuilder;
import com.yeepay.skb.biz.TransferToCustomerPartsBuilder;
import com.yeepay.skb.biz.WithdrawBuilder;
import com.yeepay.skb.results.FeeSetResult;
import com.yeepay.skb.results.TransferToCustomerPartsResult;
import com.yeepay.skb.results.WithdrawResult;
import com.yeepay.skb.util.Conts;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.atomic.DoubleAccumulator;
import java.util.stream.Collectors;

@Service
public class AgentService {

    private static final Logger logger = LoggerFactory.getLogger(AgentService.class);

    @Autowired
    private MoAgentCashMapper moAgentCashMapper;

    @Autowired
    private MoShareProfitMapper moShareProfitMapper;

    @Autowired
    private AgentProcess agentProcess;

    @Autowired
    private ManagerUserMapper managerUserMapper;

    @Autowired
    private MoPassagewayAccountMapper moPassagewayAccountMapper;

    @Autowired
    private MoUserAccountMapper moUserAccountMapper;

    @Autowired
    private PassagewayRoute passagewayRoute;

    @Autowired
    private MoWxuserinfoMapper moWxuserinfoMapper;

    @Autowired
    private BusinessService businessService;

    @Value("${me.flag}")
    private String OEM_FLAG;

    @Value("${me.operator_id}")
    private Long OPERATOR_ID;

    private String KEFU_TEL="";



    private final String defaultMaxRate="0.80%";

    @Autowired
    private ManagerUserRoleMapper managerUserRoleMapper;


    /**
     * 查代理的资金状况
     * @param userId
     * @return
     * @throws MoException
     */
    public AgentMoneyVO selMoneyByUserId(Long userId) throws MoException {
        AgentMoneyVO moneyVO=new AgentMoneyVO();
        moneyVO.setMoneyLeft(selMoneyLeft(userId));
        MoPassagewayAccountExample example=new MoPassagewayAccountExample();
        example.createCriteria().andUserIdEqualTo(userId);
        List<MoPassagewayAccount> rates=moPassagewayAccountMapper.selectByExample(example);
        if (rates.size()==0) {
            throw new MoException("未设置费率");
        }
        Double d=Double.valueOf(rates.get(0).getRate()) * 100;
        DecimalFormat df=new DecimalFormat("0.00");
        moneyVO.setRate(df.format(d)+"%");
        return moneyVO;
    }

    /**
     * 查出头像
     * @param userId
     * @return
     */
    public String selHeadUrl(Long userId){
        MoWxuserinfoExample example=new MoWxuserinfoExample();
        example.createCriteria().andUserIdEqualTo(userId);
        example.setStartIndex(0);
        example.setEndIndex(1);
        List<MoWxuserinfo> infos=moWxuserinfoMapper.selectByConditionList(example);
        if (infos.size()>0) {
            MoWxuserinfo info=infos.get(0);
            return info.getHeadimgurl();
        }
        return null;
    }

    /**
     * 查出代理的成本费率
     * @param userId
     * @return
     */
    public List<AgentCostRateVO> costRates(Long userId){
        return moPassagewayAccountMapper.usersRates(userId).stream().map(o -> {
            AgentCostRateVO vo=new AgentCostRateVO();
            vo.setCashMoney(o.getCashMoney().longValue()+"");
            vo.setPrate(MoneyUtil.dealRate(o.getRate().toString()));
            vo.setPname(o.getPassagewayName());
            return vo;
        }).collect(Collectors.toList());

        //163	86	oitinxGlfemoABf4EjLilNnXMGr0	陈龙	1	zh_CN	台州	浙江	中国	http://wx.qlogo.cn/mmopen/1lBoeFrNvTssWAwlqgaIkOYyU7ZCGda8DicCINMicEVfBn8iagsIJt09yJvqxQ6FWAUxpVicEtsK5SqEhnfnEo4tBPbPpGc0lzAr/0			1

    }

    /**
     * 未结算金额
     * @param userId
     * @return
     * @throws MoException
     */
    public String selMoneyLeft(Long userId) throws MoException {
        MoUserAccountExample example=new MoUserAccountExample();
        example.createCriteria().andUserIdEqualTo(userId);
        List<MoUserAccount> agents=moUserAccountMapper.selectByExample(example);
        if (agents.size()==0) {
            throw new MoException("账户余额信息异常");
        }
        return MoneyUtil.formatMoney(Double.valueOf(agents.get(0).getProfitLeft()));
    }

    /**
     * 转账给用户
     * @param userId
     */
    @Transactional(rollbackFor = Exception.class)
    public synchronized void transferToCustomer(Long userId,Double money) throws MoException, AgentException {
        ManagerUser user=managerUserMapper.selectByPrimaryKey(userId);
        String moneyStr=MoneyUtil.formatMoney(money);
        MoAgentCash cash=new MoAgentCash();
        cash.setAgentId(userId);
        cash.setCashTime(new Date());
        cash.setMoney(moneyStr);
        cash.setAccountBank(user.getBankName());
        cash.setAccountCardNo(user.getBankNumber());
        cash.setAccounter(user.getRealName());
        cash.setStatus(2);//发起申请//暂时默认为同意
        moAgentCashMapper.insertSelective(cash);
        //开始减钱
        agentProcess.reduceProfile(userId,money);
        //拿到易宝的编码
        MoPassagewayAccountExample accountExample=new MoPassagewayAccountExample();
        accountExample.createCriteria().andUserIdEqualTo(userId).andPassagewayIdEqualTo(1L);
        List<MoPassagewayAccount> accounts=moPassagewayAccountMapper.selectByExample(accountExample);
        if (accounts.size()==0) {
            return;
        }
        String ybcode=accounts.get(0).getAccountCode();
//        System.out.println("reduce ok "+ new Date());
        TransferToCustomerPartsBuilder builder=new TransferToCustomerPartsBuilder();
        builder.setMainCustomerNumber(Conts.customerNumber);
        builder.setCustomerNumber(ybcode);
        builder.setTransAmount(moneyStr);
        builder.setRemark("代理分润提现");
        builder.setRequestId(OEM_FLAG+"cash_"+cash.getCashId());
        TransferToCustomerPartsResult result= null;
        try {
            result = builder.exec(TransferToCustomerPartsResult.class);
        } catch (IOException e) {
            throw new MoException(e.getMessage());
        }
        if (!result.imSuccess()) {
            throw new MoException(result.getMessage());
        }
        //转账成功，开始提现
        WithdrawBuilder wbuilder=new WithdrawBuilder();
        wbuilder.setAmount(moneyStr);
        wbuilder.setCustomerNumber(ybcode);
        wbuilder.setExternalNo(OEM_FLAG+"agentcash_"+cash.getCashId());
        wbuilder.setMainCustomerNumber(Conts.customerNumber);
        wbuilder.setTransferWay("1");
//        wbuilder.setCallBackUrl(settlementCallBackUrl);
        WithdrawResult wresult= null;
        try {
            wresult = wbuilder.exec(WithdrawResult.class);
            if (!wresult.imSuccess()) {
                logger.error(cash.getCashId()+" "+wresult.getMessage());
            }
        } catch (IOException e) {
            logger.error("userId:"+userId+",money:"+money,e);
        }
    }

    /**
     * 代理提现记录
     * @param userId
     * @param fromTime
     * @return
     */
    public List<WithdrawalRecordVO> cashRecords(Long userId,Date fromTime){
        MoAgentCashExample example=new MoAgentCashExample();
        MoAgentCashExample.Criteria cri=example.createCriteria();
        cri.andAgentIdEqualTo(userId);
        if (fromTime != null) {
            cri.andCashTimeGreaterThanOrEqualTo(fromTime);
        }
        DecimalFormat df=new DecimalFormat("000000");
        example.setOrderByClause("cash_time desc");
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return moAgentCashMapper.selectByExample(example).stream().map(o -> {
            WithdrawalRecordVO vo=new WithdrawalRecordVO();
            vo.setWithdrawalNo(OEM_FLAG+"c"+df.format(o.getCashId()));
            vo.setAccountBank(o.getAccountBank());
            vo.setAccountCardNo(SecretUtil.secretBank(o.getAccountCardNo()));
            vo.setAccounter(SecretUtil.secretName(o.getAccounter()));
            vo.setWithdrawalMoney(o.getMoney());
            vo.setWithdrawalState(o.getStatus());
            vo.setWithdrawalTime(sdf.format(o.getCashTime()));
            vo.setKefuTel(KEFU_TEL);
            return vo;
        }).collect(Collectors.toList());
    }

    /**
     * 代理用户的数据统计
     * @param agentId
     * 时间 1今日 2昨日 3本周 4本月
     * @return
     */
    public List<AgentTradeVO> agentTradeCount(Long agentId){
        Calendar cal=Calendar.getInstance();
        Date now=cal.getTime();
        //今天
        cal=makeZeroTime(cal);
        Date todayStart=cal.getTime();
        List<AgentTradeVO> tradeVOS=new ArrayList<>();
        tradeVOS.add(parseCountToVO(moShareProfitMapper.agentCountByTime(agentId,todayStart,now),1));
        //昨日
        cal=Calendar.getInstance();
        cal=makeZeroTime(cal);
        cal.add(Calendar.DATE,-1);
        Date yestodayStart=cal.getTime();
        tradeVOS.add(parseCountToVO(moShareProfitMapper.agentCountByTime(agentId,yestodayStart,todayStart),2));
        //本周
        cal=Calendar.getInstance();
        cal=makeZeroTime(cal);
        cal.set(Calendar.DAY_OF_WEEK,1);
        tradeVOS.add(parseCountToVO(moShareProfitMapper.agentCountByTime(agentId,cal.getTime(),now),3));
        //本月
        cal=Calendar.getInstance();
        cal=makeZeroTime(cal);
        cal.set(Calendar.DAY_OF_MONTH,1);
        tradeVOS.add(parseCountToVO(moShareProfitMapper.agentCountByTime(agentId,cal.getTime(),now),4));
        return tradeVOS;
    }

    /**
     * 把代理数据转化为可显示的对象
     * @param count
     * @param state
     * @return
     */
    private AgentTradeVO parseCountToVO(AgentCount count,Integer state){
        if (count == null) {
            count=new AgentCount();
        }
        AgentTradeVO vo=new AgentTradeVO();
        vo.setProfits(MoneyUtil.formatMoney(count.getProfits()));
        vo.setTradeMoney(MoneyUtil.formatMoney(count.getTradeMoney()));
        vo.setTimeState(state);
        return vo;
    }

    /**
     * 零点时间制作
     * @param cal
     * @return
     */
    private Calendar makeZeroTime(Calendar cal){
        cal.set(Calendar.HOUR_OF_DAY,0);
        cal.set(Calendar.MINUTE,0);
        cal.set(Calendar.SECOND,0);
        cal.set(Calendar.MILLISECOND,0);
        return cal;
    }

    /**
     * 分润结算详情列表
     * @param userId
     * @return
     */
    public List<AgentTradeVO> tradeDetails(Long userId,Integer page){
        MoShareProfitExample example=new MoShareProfitExample();
        example.createCriteria().andAgentIdEqualTo(userId);
        example.setOrderByClause("create_time desc");
        example.setStartIndex((page-1)*15);
        example.setEndIndex(15);
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return moShareProfitMapper.selectByConditionList(example).stream().map(o -> {
            AgentTradeVO vo=new AgentTradeVO();
            vo.setProfits(MoneyUtil.formatMoney(Double.valueOf(o.getProfitMoney())));
            vo.setTradeMoney(MoneyUtil.formatMoney(Double.valueOf(o.getTradeMoney())));
            vo.setTimeArea(sdf.format(o.getCreateTime()));
            return vo;
        }).collect(Collectors.toList());

    }

    /**
     * 查询我的商户列表
     * @param agentId
     * @param page
     * @return
     */
    public List<BusinessVO> selAgentBusiness(Long agentId,Integer type,Integer page){
        if (page == null||page<=0) {
            page=1;
        }
        if (type == null) {
            type=0;
        }
        int size=15;
        int start=(page-1)*size;
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date startTime=null;
        Date endTime=null;
        Calendar cal=Calendar.getInstance();
        if (type==1) {
            endTime=cal.getTime();
            cal=makeZeroTime(cal);
            startTime=cal.getTime();
        }else if(type==2){
            endTime=cal.getTime();
            cal=makeZeroTime(cal);
            cal.set(Calendar.DAY_OF_WEEK,1);
            startTime=cal.getTime();
        }
        return managerUserMapper.simpleBusinessList(agentId,startTime,endTime,start,size).stream().map(o -> {
            BusinessVO vo=new BusinessVO();
            vo.setId(o.getBusinessId());
            vo.setCreateTime(sdf.format(o.getCreated()));
            vo.setHeadUrl(o.getHeadimgurl()==null?"http://cailifu.oss-cn-hangzhou.aliyuncs.com/img/agentman.jpg":o.getHeadimgurl());
            vo.setName(SecretUtil.secretName(o.getRealName()));
            return vo;
        }).collect(Collectors.toList());
    }

    /**
     * 是否还有下一页
     *
     * @param agentId
     * @param page
     * @return
     */
    public Boolean hasNextPageBusiness(Long agentId,Integer type,Integer page){
        if (page == null||page<=0) {
            page=1;
        }
        if (type == null) {
            type=0;
        }
        Date startTime=null;
        Date endTime=null;
        Calendar cal=Calendar.getInstance();
        if (type==1) {
            endTime=cal.getTime();
            cal=makeZeroTime(cal);
            startTime=cal.getTime();
        }else if(type==2){
            endTime=cal.getTime();
            cal=makeZeroTime(cal);
            cal.set(Calendar.DAY_OF_WEEK,1);
            startTime=cal.getTime();
        }
        int size=15;
        int now=page*size;
        ManagerUserExample example=new ManagerUserExample();
        ManagerUserExample.Criteria cri=example.createCriteria().andAgentIdEqualTo(agentId).andRealNameIsNotNull();
        if (startTime != null) {
            cri.andCreateTimeGreaterThan(startTime);
        }
        if (endTime != null) {
            cri.andCreateTimeLessThan(endTime);
        }
        int count=managerUserMapper.countByExample(example);
        return count>now;
    }


    /**
     * 商户统计
     * @param agentId
     * @return
     */
    public AgentBusinessCountVO businessCount(Long agentId){
        ManagerUserExample example=new ManagerUserExample();
        example.createCriteria().andRealNameIsNotNull().andAgentIdEqualTo(agentId);
        AgentBusinessCountVO vo=new AgentBusinessCountVO();
        vo.setAllbus(managerUserMapper.countByExample(example));
        Calendar cal=Calendar.getInstance();
        Date to=cal.getTime();
        cal=makeZeroTime(cal);
        Date from=cal.getTime();
        example.clear();
        example.createCriteria().andRealNameIsNotNull().andAgentIdEqualTo(agentId).andCreateTimeBetween(from,to);
        vo.setTodayIncrease(managerUserMapper.countByExample(example));
        cal.set(Calendar.DAY_OF_WEEK,1);
        from=cal.getTime();
        example.clear();
        example.createCriteria().andRealNameIsNotNull().andAgentIdEqualTo(agentId).andCreateTimeBetween(from,to);
        vo.setWeekIncrease(managerUserMapper.countByExample(example));
        return vo;
    }

    /**
     * 查询
     * @param busId
     * @return
     */
    public AgentSelBusrateResponse selBusRate(Long busId){
        AgentSelBusrateResponse response=new AgentSelBusrateResponse();
        //查出头像、名字、创建时间
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        BusinessSimpleInfo info=managerUserMapper.simpleBusinessById(busId);
        response.setHeadImg(info.getHeadimgurl());
        response.setName(SecretUtil.secretName(info.getRealName()));
        response.setCreatedTime(sdf.format(info.getCreated()));
        //查出通道费率
        response.setPassagewayRates(moPassagewayAccountMapper.whoPassagewayRates(busId)
        .stream().map(o -> {
                    if (StringUtils.isEmpty(o.getSettle())) {
                        o.setSettle("2");
                    }else{
                        o.setSettle(Double.valueOf(o.getSettle()).intValue()+"");
                    }
                    PassagewayRateVO vo= BeanMapper.map(o,PassagewayRateVO.class);
                    vo.setRate(MoneyUtil.dealRate(vo.getRate()));
                    return vo;
                }).collect(Collectors.toList()));
        return response.success();
    }

    public RateDetailResponse selRateDetail(Long agentId,Long businessId,Long pid) throws MoException{
        MoPassagewayAccountExample busExample=new MoPassagewayAccountExample();
        busExample.createCriteria().andUserIdEqualTo(businessId).andPassagewayIdEqualTo(pid);
        List<MoPassagewayAccount> busaccounts=moPassagewayAccountMapper.selectByExample(busExample);
        if (busaccounts.size()==0) {
            throw new MoException("用户还未激活通道");
        }
        MoPassagewayAccountExample agExample=new MoPassagewayAccountExample();
        agExample.createCriteria().andUserIdEqualTo(agentId).andPassagewayIdEqualTo(pid);
        List<MoPassagewayAccount> agaccounts=moPassagewayAccountMapper.selectByExample(agExample);
        if (agaccounts.size()==0) {
            throw new MoException("本代理账户未激活通道");
        }
        RateDetailResponse response=new RateDetailResponse();
        response.setBusNowCash(Double.valueOf(busaccounts.get(0).getCashMoney()).intValue());
        response.setBusNowRate(MoneyUtil.dealRate(busaccounts.get(0).getRate()));
        response.setMaxRate("0.8%");
        response.setMinRate(MoneyUtil.dealRate(agaccounts.get(0).getRate()));
        return response;
    }

    /**
     * 查代理的ID
     * @param busId
     * @return
     */
    public Long selAgentId(Long busId){
        ManagerUser user=managerUserMapper.selectByPrimaryKey(busId);
        return user.getAgentId();
    }
    /**
     * 修改费率
     * @param agentId
     * @param businessId
     */
    @Transactional(rollbackFor = Exception.class)
    public void modifyRate(Long pid,Long agentId,Long businessId,Double rate) throws PassagewayException {
        passagewayRoute.selwayByPid(pid).setFee(agentId,businessId,rate,null);
    }

    /**
     * 用户提升为代理
     */
    public void userUpToAgent(String bodyId,Double rate) throws MoException, IOException, PassagewayException {
        //如果没有代理权限给他加代理权限
        MoPassagewayAccountExample example=new MoPassagewayAccountExample();
        example.createCriteria().andBodyNumberEqualTo(bodyId).andPassagewayIdEqualTo(1L);
        List<MoPassagewayAccount> accounts=moPassagewayAccountMapper.selectByExample(example);
        if (accounts.size()==0) {
            throw new MoException("身份证号不存在");
        }
        MoPassagewayAccount account=accounts.get(0);
        ManagerUserRoleExample roleExample=new ManagerUserRoleExample();
        roleExample.createCriteria().andUserIdEqualTo(account.getUserId()).andRoleIdEqualTo(UserRoleType.AGENT.getRoleId());
        if (managerUserRoleMapper.countByExample(roleExample)==0) {
            ManagerUserRole role=new ManagerUserRole();
            role.setUserId(account.getUserId());
            role.setRoleId(UserRoleType.AGENT.getRoleId());
            role.setCreateTime(new Date());
            managerUserRoleMapper.insertSelective(role);
            //初始化余额
            MoUserAccount userAccount=new MoUserAccount();
            userAccount.setFrozenLeft("0.00");
            userAccount.setLastModifyTime(new Date());
            userAccount.setProfitLeft("0.00");
            userAccount.setUserId(account.getUserId());
            moUserAccountMapper.insertSelective(userAccount);
        }

        //如果当前不是这个费率，给他设置一下
        if (!Double.valueOf(account.getRate()).equals(rate)) {
            passagewayRoute.selwayByPid(1L).superSetFee(account.getUserId(),rate,0.0038d,null);
            //如果中付没开通，激活一下
            MoPassagewayAccount unpayway=moPassagewayAccountMapper.selByUserId(account.getUserId(),2L);
            if (unpayway==null) {
                businessService.activePassway(account.getUserId(),2L);
            }else{
                passagewayRoute.selwayByPid(2L).superSetFee(account.getUserId(),rate-0.001,0.0028d,null);
            }
            //处理一下联动通道
            MoPassagewayAccount linkway=moPassagewayAccountMapper.selByUserId(account.getUserId(),3L);
            if (linkway == null) {
                businessService.activePassway(account.getUserId(),3L);
            }else{
                passagewayRoute.selwayByPid(3L).superSetFee(account.getUserId(),rate-0.0002,0.0026d,null);
            }
        }
    }
}
